import { Context } from 'koa';
import { DictionaryType, DictionaryItem } from '../models/Dictionary.model';
import { success, paginated } from '../utils/response';
import { validate, commonSchemas } from '../utils/validator';
import Joi from 'joi';
import { Op } from 'sequelize';

// 类型定义
interface GetTypesQuery {
  page: number;
  pageSize: number;
  search?: string;
  status?: string;
}

interface CreateTypeData {
  code: string;
  name: string;
  english?: string;
  description?: string;
  status?: boolean;
}

interface UpdateTypeData {
  code?: string;
  name?: string;
  english?: string;
  description?: string;
  status?: boolean;
}

interface GetItemsQuery {
  page: number;
  pageSize: number;
  typeId?: string;
  search?: string;
  status?: string;
}

interface CreateItemData {
  typeId: string;
  label: string;
  english?: string;
  value: string;
  orderNum?: number;
  status?: boolean;
  description?: string;
}

interface UpdateItemData {
  label?: string;
  english?: string;
  value?: string;
  orderNum?: number;
  status?: boolean;
  description?: string;
}

/**
 * 字典控制器
 */
class DictionaryController {
  /**
   * 获取字典类型列表（分页）
   */
  async getTypes(ctx: Context) {
    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      search: Joi.string().optional().allow(''),
      status: Joi.string().optional().allow(''),
    });

    const { page, pageSize, search, status } = await validate<GetTypesQuery>(ctx.query as any, schema);

    const where: any = {};
    
    if (search) {
      where[Op.or] = [
        { code: { [Op.like]: `%${search}%` } },
        { name: { [Op.like]: `%${search}%` } },
      ];
    }

    if (status !== undefined && status !== '') {
      where.status = status === 'true';
    }

    const { count, rows } = await DictionaryType.findAndCountAll({
      where,
      limit: pageSize,
      offset: (page - 1) * pageSize,
      order: [['createdAt', 'DESC']],
      attributes: {
        include: [
          // 添加字典项数量字段
          [
            DictionaryType.sequelize!.literal(
              '(SELECT COUNT(*) FROM dictionary_items WHERE dictionary_items.type_id = DictionaryType.id)'
            ),
            'itemCount'
          ]
        ]
      },
    });

    paginated(ctx, rows, count, page, pageSize);
  }

  /**
   * 获取字典类型详情
   */
  async getTypeDetail(ctx: Context) {
    const { id } = ctx.params;

    const type = await DictionaryType.findByPk(id, {
      include: [{
        model: DictionaryItem,
        as: 'items',
        order: [['orderNum', 'ASC']],
      }],
    });

    if (!type) {
      ctx.throw(404, '字典类型不存在');
    }

    success(ctx, type);
  }

  /**
   * 创建字典类型
   */
  async createType(ctx: Context) {
    const schema = Joi.object({
      code: Joi.string().required().max(100),
      name: Joi.string().required().max(100),
      english: Joi.string().optional().allow('').max(100),
      description: Joi.string().optional().allow('').max(500),
      status: Joi.boolean().optional(),
    });

    const data = await validate<CreateTypeData>(ctx.request.body as any, schema);

    // 检查编码是否已存在
    const existing = await DictionaryType.findOne({
      where: { code: data.code },
    });

    if (existing) {
      ctx.throw(400, '字典编码已存在');
    }

    const type = await DictionaryType.create({
      ...data,
      tenantId: (ctx.state.user as any).tenantId,
    });

    success(ctx, type, '创建成功');
  }

  /**
   * 更新字典类型
   */
  async updateType(ctx: Context) {
    const { id } = ctx.params;
    const schema = Joi.object({
      code: Joi.string().optional().max(100),
      name: Joi.string().optional().max(100),
      english: Joi.string().optional().allow('').max(100),
      description: Joi.string().optional().allow('').max(500),
      status: Joi.boolean().optional(),
    });

    const data = await validate<UpdateTypeData>(ctx.request.body as any, schema);

    const type = await DictionaryType.findByPk(id);
    if (!type) {
      ctx.throw(404, '字典类型不存在');
    }

    // 如果修改编码，检查是否已存在
    if (data.code && data.code !== type.code) {
      const existing = await DictionaryType.findOne({
        where: { code: data.code },
      });
      if (existing) {
        ctx.throw(400, '字典编码已存在');
      }
    }

    await type.update(data);
    success(ctx, type, '更新成功');
  }

  /**
   * 删除字典类型
   */
  async deleteType(ctx: Context) {
    const { id } = ctx.params;

    const type = await DictionaryType.findByPk(id);
    if (!type) {
      ctx.throw(404, '字典类型不存在');
    }

    // 删除关联的字典项
    await DictionaryItem.destroy({
      where: { typeId: id },
    });

    await type.destroy();
    success(ctx, null, '删除成功');
  }

  /**
   * 获取字典项列表（分页）
   */
  async getItems(ctx: Context) {
    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      typeId: Joi.string().uuid().optional().allow(''),
      search: Joi.string().optional().allow(''),
      status: Joi.string().optional().allow(''),
    });

    const { page, pageSize, typeId, search, status } = await validate<GetItemsQuery>(ctx.query as any, schema);

    const where: any = {};
    
    if (typeId) {
      where.typeId = typeId;
    }

    if (search) {
      where[Op.or] = [
        { label: { [Op.like]: `%${search}%` } },
        { value: { [Op.like]: `%${search}%` } },
      ];
    }

    if (status !== undefined && status !== '') {
      where.status = status === 'true';
    }

    const { count, rows } = await DictionaryItem.findAndCountAll({
      where,
      limit: pageSize,
      offset: (page - 1) * pageSize,
      order: [['orderNum', 'ASC'], ['createdAt', 'DESC']],
      include: [{
        model: DictionaryType,
        as: 'type',
        attributes: ['id', 'code', 'name'],
      }],
    });

    paginated(ctx, rows, count, page, pageSize);
  }

  /**
   * 创建字典项
   */
  async createItem(ctx: Context) {
    const schema = Joi.object({
      typeId: Joi.string().uuid().required(),
      label: Joi.string().required().max(100),
      english: Joi.string().optional().allow('').max(100),
      value: Joi.string().required().max(100),
      orderNum: Joi.number().optional(),
      status: Joi.boolean().optional(),
      description: Joi.string().optional().allow('').max(500),
    });

    const data = await validate<CreateItemData>(ctx.request.body as any, schema);

    // 检查字典类型是否存在
    const type = await DictionaryType.findByPk(data.typeId);
    if (!type) {
      ctx.throw(404, '字典类型不存在');
    }

    const item = await DictionaryItem.create(data as any);
    success(ctx, item, '创建成功');
  }

  /**
   * 更新字典项
   */
  async updateItem(ctx: Context) {
    const { id } = ctx.params;
    const schema = Joi.object({
      label: Joi.string().optional().max(100),
      english: Joi.string().optional().allow('').max(100),
      value: Joi.string().optional().max(100),
      orderNum: Joi.number().optional(),
      status: Joi.boolean().optional(),
      description: Joi.string().optional().allow('').max(500),
    });

    const data = await validate<UpdateItemData>(ctx.request.body as any, schema);

    const item = await DictionaryItem.findByPk(id);
    if (!item) {
      ctx.throw(404, '字典项不存在');
    }

    await item.update(data);
    success(ctx, item, '更新成功');
  }

  /**
   * 删除字典项
   */
  async deleteItem(ctx: Context) {
    const { id } = ctx.params;

    const item = await DictionaryItem.findByPk(id);
    if (!item) {
      ctx.throw(404, '字典项不存在');
    }

    await item.destroy();
    success(ctx, null, '删除成功');
  }

  /**
   * 根据字典类型编码获取字典项（公开接口）
   */
  async getItemsByCode(ctx: Context) {
    const { code } = ctx.params;

    const type = await DictionaryType.findOne({
      where: { code, status: true },
      include: [{
        model: DictionaryItem,
        as: 'items',
        where: { status: true },
        required: false,
        order: [['orderNum', 'ASC']],
      }],
    });

    if (!type) {
      ctx.throw(404, '字典类型不存在');
    }

    success(ctx, type.items || []);
  }
}

export default new DictionaryController();


